package network

import (
	"Alpaca/log"
	"net"
	"sync"
)

type TcpConn struct {
	sync.Mutex
	conn      net.Conn
	writeChan chan []byte
	closeFlag bool
	msgParser *MsgParser
}

type ConnSet map[net.Conn]struct{}

func NewTcpConn(conn net.Conn, writeChanlen int, msgParser *MsgParser) *TcpConn {
	tcpConn := new(TcpConn)
	tcpConn.conn = conn
	tcpConn.msgParser = msgParser
	tcpConn.writeChan = make(chan []byte, writeChanlen)

	go func() {
		for msg := range tcpConn.writeChan {
			if msg == nil { //chan关闭
				break
			}

			_, err := conn.Write(msg)
			if err != nil {
				break
			}
		}

		tcpConn.Destroy()
	}()

	return tcpConn
}

func (tcpConn *TcpConn) doDestroy() {
	tcpConn.conn.Close() //关闭连接,连接多次close不会报错

	if !tcpConn.closeFlag {
		close(tcpConn.writeChan)
		tcpConn.closeFlag = true
	}
}

func (tcpConn *TcpConn) Destroy() {
	tcpConn.Lock()
	defer tcpConn.Unlock()

	tcpConn.doDestroy()
}

func (tcpConn *TcpConn) Close() { //只关闭管道
	tcpConn.Lock()
	defer tcpConn.Unlock()

	if !tcpConn.closeFlag {
		tcpConn.dowrite(nil) //加过锁了直接dowrite,等读到了nil就会关闭chan
		tcpConn.closeFlag = true
	}
}

func (tcpConn *TcpConn) Read(b []byte) (int, error) {
	return tcpConn.conn.Read(b)
}

func (tcpConn *TcpConn) dowrite(b []byte) {
	if len(tcpConn.writeChan) == cap(tcpConn.writeChan) {
		log.Debug("chan is full close connection")
		tcpConn.doDestroy() //此时已加锁直接执行销毁的步骤
		return
	}

	tcpConn.writeChan <- b
}

func (tcpConn *TcpConn) Write(b []byte) {
	//往写缓冲区内写入数据
	tcpConn.Lock()
	defer tcpConn.Unlock()

	if tcpConn.closeFlag || b == nil {
		return
	}

	tcpConn.dowrite(b)
}

func (tcpConn *TcpConn) LocalAddr() net.Addr {
	return tcpConn.conn.LocalAddr()
}

func (tcpConn *TcpConn) RemoteAddr() net.Addr {
	return tcpConn.conn.RemoteAddr()
}

func (tcpConn *TcpConn) ReadMsg() ([]byte, error) {
	return tcpConn.msgParser.ParseData(tcpConn)
}

func (tcpConn *TcpConn) WriteMsg(args ...[]byte) error {
	return tcpConn.msgParser.AttachHeader(tcpConn, args...)
}
